#using perl to describe a card game in my home town YaAn SiChuan
#Zhang Jiening
#2007-05-11

#use strict
#use Color::Output;

$aidInfoShow = 0;

@cards = ();
#------cards preparing
#{{{
#------there are 21 kind of cards in this game, each kind have 4 cars, so there are 84 cards in this game
%cardName = (
	0  => '*tian----',
	1  => ' 45------',
	2  => ' 36------',
	3  => '*di------',
	4  => ' 35------',
	5  => ' 26------',
	6  => '*ren-----',
	7  => ' 34------',
	8  => ' 25------',
	9  => '*he------',
	10 => ' 14------',
	11 => ' 23------',
	12 => 'meizi----',
	13 => 'chang3---',
	14 => 'chang2---',
	15 => '15-------',
	16 => '16-------',
	17 => '46-------',
	18 => '56-------',
	19 => 'dingding-',
	20 => 'erhong---');

#------there are 7 grade, ever kind of cars have their own grade
%cardPingJi = (0 => 'xideng',
			   1 => 'tian',
		   	   2 => 'di',
		   	   3 => 'ren',
	   		   4 => 'he',
			   5 => 'zhong',
			   6 => 'yaoguai',
			   7 => 'dianshu');

#------if a card have the grade 'dianshu', its color must be specified either red or black
%cardColor = (0 => 'nocolor',
			  1 => 'red',
		  	  2 => 'black');

#------type
%loopType = (0 => 'pingji',
			 1 => 'dianshu',
			 2 => 'pingdian');

#------card can be in such states below		 
%cardState = (0 => 'unDispense',
			  1 => 'Aplayer',
			  2 => 'Aget',
			  3 => 'Bplayer',
			  4 => 'Bget',
			  5 => 'Cplayer',
			  6 => 'Cget',
			  7 => 'Dplayer',
			  8 => 'Dget',
			  9 => 'lost');

@cards = ();
#------step 1, to prepare all the 84 cards
#------name, pingji,color,state,usedloop
$cards[0]  = [(0, 1, 0, 0, 0)];
$cards[4]  = [(1, 7, 1, 0, 0)];
$cards[8]  = [(2, 7, 2, 0, 0)];
$cards[12] = [(3, 2, 0, 0, 0)];
$cards[16] = [(4, 7, 2, 0, 0)];
$cards[20] = [(5, 7, 2, 0, 0)];
$cards[24] = [(6, 3, 0, 0, 0)];
$cards[28] = [(7, 7, 1, 0, 0)];
$cards[32] = [(8, 7, 2, 0, 0)];
$cards[36] = [(9, 4, 0, 0, 0)];
$cards[40] = [(10,7, 1, 0, 0)];
$cards[44] = [(11,7, 2, 0, 0)];
$cards[48] = [(12,5, 0, 0, 0)];
$cards[52] = [(13,5, 0, 0, 0)];
$cards[56] = [(14,5, 0, 0, 0)];
$cards[60] = [(15,6, 0, 0, 0)];
$cards[64] = [(16,6, 0, 0, 0)];
$cards[68] = [(17,6, 0, 0, 0)];
$cards[72] = [(18,6, 0, 0, 0)];
$cards[76] = [(19,0, 0, 0, 0)];
$cards[80] = [(20,0, 0, 0, 0)];

$i,$j;

for($i = 0; $i<21; ++$i)
{   
	#$cards[$i*4+1] = $cards[$i*4+2] = $cards[$i*4+3] = $cards[$i*4]; 
	
	$cards[$i*4+1] = [($cards[$i*4][0], $cards[$i*4][1], $cards[$i*4][2], $cards[$i*4][3], $cards[$i*4][4] )];
   	$cards[$i*4+2] = [($cards[$i*4][0], $cards[$i*4][1], $cards[$i*4][2], $cards[$i*4][3], $cards[$i*4][4] )];
   	$cards[$i*4+3] = [($cards[$i*4][0], $cards[$i*4][1], $cards[$i*4][2], $cards[$i*4][3], $cards[$i*4][4] )];
}

for($i=0; $i<84; ++$i)
{
	#print "\n$i\t$cards[$i]";
	#print "\n$i\t$cards[$i][0]\t$cards[$i][1]\t$cards[$i][2]";

	#print "\n$i\t$cardName{$cards[$i][0]}\t$cardPingJi{$cards[$i][1]}\t$cardColor{$cards[$i][2]}";
}

print "\n";
#}}}

#------step 2, shuffle, and get the cards hand round
#{{{
srand(time());

%cardsHandRound;

for($i=0; $i<84; ++$i)
{
	$tmpV = rand();
		
	while( exists( $cardsHandRound{$tmpV} ) )
	{
		$tmpV = rand();		
	}

	$cardsHandRound{$tmpV} = $i;
}

#------get the cards hand round between the three player
#
%AplayerBank = {};
%BplayerBank = {};
%CplayerBank = {};
%DplayerBank = {};
	#dcount 当盘翻倍
	#pcount 当盘点数

@playerBanks;
$playerBanks[0] = \%AplayerBank;
$playerBanks[1] = \%BplayerBank;
$playerBanks[2] = \%CplayerBank;
$playerBanks[3] = \%DplayerBank;

@AplayerCards;
@BplayerCards;
@CplayerCards;
@DplayerCards;

@playersCards;
$playersCards[0] = \@AplayerCards;
$playersCards[1] = \@BplayerCards;
$playersCards[2] = \@CplayerCards;
$playersCards[3] = \@DplayerCards;

$handRoungCount = 0;

%playerToIndex = ('A' => 0, 
				  'B' => 1, 
				  'C' => 2, 
				  'D' => 3);

foreach $tmpKey (sort keys(%cardsHandRound))
{
	$tmpCardIndex = $cardsHandRound{$tmpKey};
	#print "\n$i\t$tmpKey\t$tmpCardIndex";
	if($handRoungCount%3==0)
	{
		$AplayerCards[$handRoungCount/3]=$tmpCardIndex;
		$cards[$tmpCardIndex][3] = 1;
	}
	elsif($handRoungCount%3==1)
	{
		$BplayerCards[$handRoungCount/3]=$tmpCardIndex;
		$cards[$tmpCardIndex][3] = 3;
	}
	else
	{
		$CplayerCards[$handRoungCount/3]=$tmpCardIndex;
		$cards[$tmpCardIndex][3] = 5;
	}
	
	++$handRoungCount;
}

sortCards('A');
sortCards('B');
sortCards('C');

%UnicValidInputA;
%UnicValidInputB;
%UnicValidInputC;
%UnicValidInputD;
		#isValid 		0 false, 1 true
		#type 			value in loopType
		#subtype   		value in loopSubType
		#cardCount 		the number of the combination of the cards
		#cardName       the first card's name of the combination
		#cardsArr 		ref to the array of the cards' index of the player

%playerOptionA;
%playerOptionB;
%playerOptionC;
%playerOptionD;
@arrayUVI = (\%UnicValidInputA, \%UnicValidInputB, \%UnicValidInputC, \%UnicValidInputD);
@arrayOption = (\%playerOptionA, \%playerOptionB, \%playerOptionC, \%playerOptionD);
#}}}

#------step3 begin to play loop after loop
#{{{

$currentLoop = 0;
$currentPlayer = 'A';
$nextPlayer;
$winnerPlayerLoop = $currentPlayer;

while(1)
{
	++$currentLoop;
	showPlayerCards($currentPlayer);
	print "\ninput corresponding characters of the cards you want put\n";
	$playerInput = <STDIN>;

	parseInput($currentPlayer, $playerInput, $arrayUVI[$playerToIndex{$currentPlayer}]);
	while($arrayUVI[$playerToIndex{$currentPlayer}]->{'isValid'} == 0)
	{
		print"\nnot a valid input, again please\n";

		%{$arrayUVI[$playerToIndex{$currentPlayer}]} = {};
			
		print "\ninput corresponding characters of the cards you want put\n";
		$playerInput = <STDIN>;

		parseInput($currentPlayer, $playerInput, $arrayUVI[$playerToIndex{$currentPlayer}]);
	}

	handShow($currentLoop, $currentPlayer, $arrayUVI[$playerToIndex{$currentPlayer}]);
	$winnerPlayerLoop = $currentPlayer;

	if($currentPlayer eq 'A')
	{
		$nextPlayer = 'B';
	}
	elsif($currentPlayer eq 'B')
	{
		$nextPlayer = 'C';
	}
	elsif($currentPlayer eq 'C')
	{
		$nextPlayer = 'A';
	}
	
	if(1 == cardChooseToPlay($nextPlayer, $winnerPlayerLoop))
	{
		$winnerPlayerLoop = $nextPlayer;
	}
	else
	{
		print "\n :(((((((((((((((( player $nextPlayer can not to play more powerful cards\n";
		print "press any key to continue\n";
		#$tmpInput = <STDIN>;
	}

	$currentPlayer = $nextPlayer;
	if($currentPlayer eq 'A')
	{
		$nextPlayer = 'B';
	}
	elsif($currentPlayer eq 'B')
	{
		$nextPlayer = 'C';
	}
	elsif($currentPlayer eq 'C')
	{
		$nextPlayer = 'A';
	}
	
	if(1 == cardChooseToPlay($nextPlayer, $winnerPlayerLoop))
	{
		$winnerPlayerLoop = $nextPlayer;
	}
	else
	{
		print "\n :(((((((((((((((( player $nextPlayer  can not to play more powerful cards\n";
		print "press any key to continue\n";
		#$tmpInput = <STDIN>;
	}
	
	print "\nthe loop winner is $winnerPlayerLoop\n";

	$currentPlayer = $winnerPlayerLoop;

	cardGet($winnerPlayerLoop);

	%UnicValidInputA={};
	%UnicValidInputB={};
	%UnicValidInputC={};
	%UnicValidInputD={};
	%playerOptionA={};
	%playerOptionB={};
	%playerOptionC={};
	%playerOptionD={};

	$resJugeWin = computeWin($winnerPlayerLoop);
	if(1==$resJugeWin)
	{
		print "\nnow you can choose to finish game\n";
	   	print"	but you have only 14 cards get, so you do not win the game as other two players\n";
		print "\nfinish the game? yes or no\n";
		$chooseToFinish = <STDIN>;
		if($chooseToFinish eq "yes\n")
		{
			print "$winnerPlayerLoop choose to finish the game\n";
			last;
		}
	}
	elsif(2 == $resJugeWin)
	{
		print "\nnow you can choose to finish game\n";
	    print "your point count is \t $playerBanks[$playerToIndex{$winnerPlayerLoop}]->{'pcount'}\n"; 
		print "your double count is\t $playerBanks[$playerToIndex{$winnerPlayerLoop}]->{'dcount'}\n";
		print "\nfinish the game? yes or no\n";

		$chooseToFinish = <STDIN>;
		if($chooseToFinish eq "yes\n")
		{
			print "$winnerPlayerLoop choose to finish the game\n";
			last;
		}
	}

	#last;
}
#}}}

#--------------------------------------------------------------------
#---sub function start from here
#--------------------------------------------------------------------

sub cardChooseToPlay
{
	my($nowPlayer, $prePlayer) = @_;
	my($refNowPlayerUVI, $refNowPlayerOption);
	my($refPrePlayerUVI);
	
	if(exists($playerToIndex{$nowPlayer}) && exists($playerToIndex{$prePlayer}))
	{
		$refNowPlayerUVI 	= $arrayUVI[$playerToIndex{$nowPlayer}];
		$refNowPlayerOption = $arrayOption[$playerToIndex{$nowPlayer}];

		$refPrePlayerUVI 	= $arrayUVI[$playerToIndex{$prePlayer}];
	}
	else
	{		
		print "wrong input for parseInput call\n\n";
		return 0;
	}
	
	%{$refNowPlayerOption} = {};	
	showPlayerCards($nowPlayer);
    
	checkPlayerCard($nowPlayer, $refPrePlayerUVI, $refNowPlayerOption);
	
	if($refNowPlayerOption->{'checkResult'} eq 'success')
	{	
		while(0 == cardCompare($refNowPlayerUVI, $refPrePlayerUVI))
		{
			%{$refNowPlayerUVI} ={};

			#print "\nyou must show your more powerful cards\n";

			print "\ninput corresponding characters of the cards you want put\n";
			$playerInput = <STDIN>;

			parseInput($nowPlayer, $playerInput, $refNowPlayerUVI);
			while($refNowPlayerUVI->{'isValid'} == 0)
			{
				print"\nnot a valid input, again please\n";

				%{$refNowPlayerUVI} = {};

				print "\ninput corresponding characters of the cards you want put\n";
				$playerInput = <STDIN>;

				parseInput($nowPlayer, $refPrePlayerUVI, $refNowPlayerOption);
			}
		}

		handShow($currentLoop, $nowPlayer, $refNowPlayerUVI);
		return 1;
	}
	else
	{
		print "\ncan not to play more powerful cards\n";
		return 0;
	}
}

#function to juge whether the play can win the game
#0 not
#1 not win but finish 
#2 win
sub computeWin
{
	my($tmpPlayer) = @_;

	my($tmpArrElem, $refPlayerCards);
	my($tmpCardState, $tmpCardName);
	my($tmpCardGetCount, %doubleCount);
	my($refPlayerBank);

	if(exists($playerToIndex{$tmpPlayer}))
	{
		$refPlayerCards = $playersCards[$playerToIndex{$tmpPlayer}];
		$refPlayerBank = $playerBanks[$playerToIndex{$tmpPlayer}];
	}
	else
	{		
		print "wrong input for parseInput call\n\n";
		return 0;
	}
	
	for($i=0; $i<28; ++$i)
	{
		$tmpCardState = $cards[$refPlayerCards->[$i]][3];

		if($tmpCardState%2 == 0) #---card get
		{
			++$tmpCardGetCount;
		}
	}

	if($tmpCardGetCount<14)
	{
		return 0;
	}
	if($tmpCardGetCount==14)
	{
		return 1;
	}
	
	$refPlayerBank->{'pcount'} = $tmpCardGetCount-14;

	return 2;
}

sub cardGet
{
	my($tmpPlayer) = @_;
	my($tmpArrElem, $refPlayerCards);
	my($refPlayerBank);
	my($tmpCardName, $tmpWinCountKey);
	my(%doubleCount);
	my($refUVI);
	if(exists($playerToIndex{$tmpPlayer}))
	{
		$refPlayerCards = $playersCards[$playerToIndex{$tmpPlayer}];
		$refPlayerBank = $playerBanks[$playerToIndex{$tmpPlayer}];
		$refUVI = $arrayUVI[$playerToIndex{$tmpPlayer}];
	}
	else
	{
		print "wrong input for parseInput call\n\n";
		return ;
	}

	print "\nin function cardGet\n";
	
	foreach $tmpArrElem (@{$refUVI->{'cardsArr'}})
	{
		print "set $refPlayerCards->[$tmpArrElem] G\n ";
		
		$tmpCardName  = $cards[$refPlayerCards->[$tmpArrElem]][0];
		
		$cards[$refPlayerCards->[$tmpArrElem]][3] = 2*($playerToIndex{$tmpPlayer} + 1);
		
		if(exists($doubleCount{$tmpCardName}))
		{
			 $doubleCount{$tmpCardName} += 1;
		}
		else
		{
			$doubleCount{$tmpCardName} = 1;
		}
	}

	for $tmpWinCountKey (keys %doubleCount)
	{
		if($doubleCount{$tmpWinCountKey}==3)
		{
			if(exists($refPlayerBank->{'dcount'}))
			{
				$refPlayerBank->{'dcount'} *= 2;
			}
			else
			{
				$refPlayerBank->{'dcount'} = 2;
			}
		}
		elsif($doubleCount{$tmpWinCountKey}==4)
		{
			if(exists($refPlayerBank->{'dcount'}))
			{
				$refPlayerBank->{'dcount'} *= 4;
			}
			else
			{
				$refPlayerBank->{'dcount'} = 4;
			}
		}
	}
}

sub cardCompare
{
	my($refUVIcur, $refUVIpre) = @_;
		#isValid 		0 false, 1 true
		#type 			value in loopType
		#cardCount 		the number of the combination of the cards
		#cardName       the first card's name of the combination
		#cardsArr 		ref to the array of the cards' index of the player

	print "\nin function cardCompare\n";
	if(!exists($refUVIcur->{'isValid'}) || !exists($refUVIpre->{'isValid'}))
	{
		return 0;
	}

	showUVInfo($refUVIcur);
	showUVInfo($refUVIpre);

	if($refUVIcur->{'isValid'} != 1 || $refUVIpre->{'isValid'} != 1)
	{
		return 0;
	}
	if($refUVIcur->{'type'} != $refUVIpre->{'type'})
	{
		print "\nmistake type of your cards to show\n";
		return 0;
	}
	if($refUVIcur->{'cardCount'} != $refUVIpre->{'cardCount'})
	{
		print "\nmistake number of your cards to show\n";
		return 0;
	}

	if($refUVIcur->{'type'} != 1)
	{
		if($refUVIcur->{'cardName'} >=  $refUVIpre->{'cardName'})
		{
			print "\nmistake pingji of your cards to show\n";
			return 0;
		}
	}
	else
	{
		if($refUVIpre->{'cardName'} == 5 || $refUVIpre->{'cardName'} == 4)
		{
			if($refUVIcur->{'cardName'} != 2)
			{
				print "\nonly 36 can be show\n";
				return 0;
			}
		}
		else
		{
			if($refUVIcur->{'cardName'} >=  $refUVIpre->{'cardName'})
			{
				print "\nmistake dian shu of your cards to show\n";
				return 0;
			}
			if($cards[4*$refUVIcur->{'cardName'}][2] != $cards[4*$refUVIpre->{'cardName'}][2])
			{
				print "\nmistake color of your cards to show\n";
				return 0;
			}
		}
	}

	return 1;
}

sub handShow
{
	my($loopnum, $tmpPlayer, $tmprefUVI) = @_;
	my($tmpIndex, $refPlayerCards);
	if(exists($playerToIndex{$tmpPlayer}))
	{
		$refPlayerCards = $playersCards[$playerToIndex{$tmpPlayer}];
	}
	else
	{
		print "wrong input for parseInput call\n\n";
		$tmprefUVI->{'isValid'} = 0;
		return ;
	}

	for($i=0; $i< $tmprefUVI->{'cardCount'}; ++$i)
	{
		$tmpIndex = $tmprefUVI->{'cardsArr'}->[$i];
		$cards[$refPlayerCards->[$tmpIndex]][3] = 9;
		$cards[$refPlayerCards->[$tmpIndex]][4] = $loopnum;
	}
}

#------ 检查当前玩家手中的牌是否足以接下上家的出牌
#{{{
sub checkPlayerCard
{
	my($tmpPlayer, $refUVI, $refOption) = @_;
	my($refPlayerCards);

	my($tmpCardIndex);
	my($tmpCompareCardIndex);
	my($tmpPinDianIndex);
	my($tmpOptionKey);
	my($tmpOptionValue);
	my($tmpArrLen);

	if(0 != $aidInfoShow)
	{
		print "\nin func checkPlayerCard:\n";
		showUVInfo($refUVI);
	}
	if(exists($playerToIndex{$tmpPlayer}))
	{
		$refPlayerCards = $playersCards[$playerToIndex{$tmpPlayer}];
	}
	else
	{
		$theOption{'checkResult'} = 'fail'; 
		print "wrong input for checkPlayerCard call\n\n";
		return ;
	}
    
	#------上家的牌如果品或是点都在顶级，当前玩家pass
	if($refUVI->{'cardName'} < 3)
	{
		$refOption->{'checkResult'} = 'pass';
		return;
	}

	$tmpCompareCardIndex = $refUVI->{'cardName'}*4;

	print "\n";

	#------如果上家出牌是品级
	if($refUVI->{'type'} == 0)
	{
		for($i = 0; $i<28; ++$i)
		{
			$tmpCardIndex = $refPlayerCards->[$i];

			#------跳过 出过的牌  已经得到的牌
			if($cards[$tmpCardIndex][3] == 9 || $cards[$tmpCardIndex][3]%2 == 0)
			{
				next;
			}
			#------找到品级比上家牌高的
			if($cards[$tmpCardIndex][1] < $cards[$tmpCompareCardIndex][1] )
			{
				print "$cards[$tmpCardIndex][0]\t";
				if(exists($refOption->{$cards[$tmpCardIndex][0]}))
				{
					push(@{$refOption->{$cards[$tmpCardIndex][0]}}, $i); 
				}
				else
				{
					$refOption->{$cards[$tmpCardIndex][0]} = [($i)];	
				}
			}
		}
	}
	#------如果上家出牌是点数
	elsif($refUVI->{'type'} ==1)
	{
		for($i = 0; $i<28; ++$i)
		{
			$tmpCardIndex = $refPlayerCards->[$i];

			#------跳过 出过的牌  已经得到的牌
			if($cards[$tmpCardIndex][3] == 9 || $cards[$tmpCardIndex][3]%2 == 0)
			{
				next;
			}
			#------只找点数牌
			if($cards[$tmpCardIndex][1] != 7)
			{
				next;
			}
			#------如果上家是35 或是 26
			if($cards[$tmpCompareCardIndex][0] == 4 || 
			   $cards[$tmpCompareCardIndex][0] == 5)
			{
				#------只有36可以
				if($cards[$tmpCardIndex][0] != 2)
				{
					next;
				}
			}
			#------其余的点数的判断
			else
			{
				#------点数的颜色要对
				if($cards[$tmpCardIndex][2] != $cards[$tmpCompareCardIndex][2])
				{
					next;
				}
				#------点数要大()
				if($cards[$tmpCardIndex][0] >= $cards[$tmpCompareCardIndex][0])
				{
					next;
				}
			}
			
			print "$cards[$tmpCardIndex][0]\t";

			if(exists($refOption->{$cards[$tmpCardIndex][0]}))
			{
				push(@{$refOption->{$cards[$tmpCardIndex][0]}}, $i); 
			}
			else
			{
				$refOption->{$cards[$tmpCardIndex][0]} = [($i)];	
			}
		}
	}
	#------如果上家出牌是品级+点数
	elsif($refUVI->{'type'} == 2)
	{
		for($i = 0; $i<28; ++$i)
		{
			$tmpCardIndex = $refPlayerCards->[$i];

			#------跳过 出过的牌  已经得到的牌
			if($cards[$tmpCardIndex][3] == 9 || $cards[$tmpCardIndex][3]%2 == 0)
			{
				next;
			}
			if(int($cards[$tmpCardIndex][0]/3) >= int($cards[$tmpCompareCardIndex][0]/3))
			{
				next;
			}
			$tmpPinDianIndex = 3 * int($cards[$tmpCardIndex][0]/3);

			if(0 != $aidInfoShow)
			{
				print "$i-$cards[$tmpCardIndex][0]-$tmpPinDianIndex\t";
			}

			if(exists($refOption->{$tmpPinDianIndex}))
			{
				push(@{$refOption->{$tmpPinDianIndex}[0]},$i); 
				if($cards[$tmpCardIndex][0]%3==0)
				{
					$refOption->{$tmpPinDianIndex}->[1] = 1;
				}
				else
				{
					$refOption->{$tmpPinDianIndex}->[2] = 1;

				}
			}
			else
			{
				if($cards[$tmpCardIndex][0]%3==0)
				{
					$refOption->{$tmpPinDianIndex} = [([($i)],1,0)];	
				}
				else
				{
					$refOption->{$tmpPinDianIndex} = [([($i)],0,1)];
				}
			}
		}
	}
	else
	{
		$refOption->{'checkResult'} = 'fail'; 
		print"\nthe UVI struct do not contain legal value\n";
		return;		
	}

	foreach $tmpOptionKey (sort keys(%{$refOption}))
	{
		if($tmpOptionKey ne 'checkResult')
		{
			if($refUVI->{'type'} == 2)
			{
				if(0 != $aidInfoShow)
				{
					print "\nping $refOption->{$tmpOptionKey}->[1]\t";
					print "dian $refOption->{$tmpOptionKey}->[2]\n";
				}
				if(1 == $refOption->{$tmpOptionKey}->[1] &&
				   1 ==	$refOption->{$tmpOptionKey}->[2])
			    {
					$tmpArrLen = @{$refOption->{$tmpOptionKey}[0]};
					
					if(0 != $aidInfoShow)
					{
						print "\nlength compare $tmpArrLen $refUVI->{'cardCount'}\n";
						foreach $tmpOptionValue (@{$refOption->{$tmpOptionKey}[0]})
						{
							print "$tmpOptionValue\t"; 
						}
					}
					if($refUVI->{'cardCount'} <= $tmpArrLen)
					{
						 $refOption->{'checkResult'} = 'success';
					}
					else
					{
						 delete $refOption->{$tmpOptionKey};
					}	
			    }
				else
				{
					delete $refOption->{$tmpOptionKey};
				}
				
			}
			else
			{
				$tmpArrLen = @{$refOption->{$tmpOptionKey}};
				
				if(0 != $aidInfoShow)
				{
					print "\n length compare $tmpArrLen $refUVI->{'cardCount'}\n";
					foreach $tmpOptionValue (@{$refOption->{$tmpOptionKey}})
					{
						print "$tmpOptionValue\t";
					}
				}

				if($refUVI->{'cardCount'} <= $tmpArrLen)
				{
					 $refOption->{'checkResult'} = 'success';
				}
				else
				{
					delete $refOption->{$tmpOptionKey};
				}
				
			}		
		}
	}
}
#}}}

sub showUVInfo
{
	my($refUVI) = @_;

	if($aidInfoShow == 0)
	{
		return;
	}
	print "\ncontent of tmpCheck";
	foreach $tmpCheck (sort keys(%{$refUVI}))
	{
		print "\n$tmpCheck $refUVI->{$tmpCheck}";
		if($tmpCheck eq 'cardsArr')
		{
			print "\n$refUVI->{'cardCount'}";
			for($i=0; $i< $refUVI->{'cardCount'}; ++$i)
			{
				print "$i = $refUVI->{'cardsArr'}->[$i] \t";
			}
		}
	}
	print "\n";
}

#------ 察看保证当前用户的出牌合乎规则
#{{{
sub parseInput
{
	my($tmpPlayer, $tmpInput, $refUVI) = @_;
	my(%unicInput);
	my($charCheck);
	my($refPlayerCards);

	if(exists($playerToIndex{$tmpPlayer}))
	{
		$refPlayerCards = $playersCards[$playerToIndex{$tmpPlayer}];
	}
	else
	{
		print "wrong input for parseInput call\n\n";
		$refUVI->{'isValid'} = 0;
		return ;
	}
	
	$tmpInput = lc($tmpInput);
	my($tmpState);
	for($i=0; $i<length($tmpInput); ++$i)
	{
		$charCheck = substr($tmpInput,$i,1);
		if(ord($charCheck)<ord('a') || ord($charCheck)>(ord('a')+27))
		{
			next;
		}

		$tmpState = $cards[$refPlayerCards->[ord($charCheck) - ord('a')]][3];

		if($tmpState == 9 || $tmpState%2 == 0)
		{
			next;
		}

		$unicInput{$charCheck} = ord($charCheck) - ord('a');		
	}

	if(keys(%unicInput)<1)
	{
		$refUVI->{'isValid'} = 0;
		return ;
	}
	
	$refUVI->{'type'} = -1;
	$refUVI->{'cardCount'} = keys(%unicInput);
	$refUVI->{'cardsArr'} = [];
	$refUVI->{'cardName'} = '';
	$refUVI->{'isValid'} = 1;

	my($tmpUnicCout);
	$tmpUnicCout = 0;
	my($tmpKey);

	foreach $tmpKey (sort keys(%unicInput))
	{
		$refUVI->{'cardsArr'}->[$tmpUnicCout] =  $unicInput{$tmpKey};
		print "\n$tmpKey\t";
		print "$cardName{$cards[$refPlayerCards->[$unicInput{$tmpKey}]][0]}\t";
		print "$refUVI->{'cardsArr'}->[$tmpUnicCout]";	

		++$tmpUnicCout;
		
		#------第一张牌的处理逻辑
		if(-1 == $refUVI->{'type'})
		{
			if(7 != $cards[$refPlayerCards->[$unicInput{$tmpKey}]][1])
			{
				$refUVI->{'type'} = 0;
			}
			else
			{
				$refUVI->{'type'} = 1;
			}

			$refUVI->{'cardName'} = $cards[$refPlayerCards->[$unicInput{$tmpKey}]][0]; 
		}
		else
		{
			#------这张牌是品级的处理逻辑
			if(7 != $cards[$refPlayerCards->[$unicInput{$tmpKey}]][1])
			{
				#------当前牌组合是品级
				if(0 == $refUVI->{'type'})
				{
					if($refUVI->{'cardName'} ne $cards[$refPlayerCards->[$unicInput{$tmpKey}]][0])
					{
						 $refUVI->{'isValid'} = 0;
						 last;
					}
				}
				#------当前牌组合是点数
				if(1 ==  $refUVI->{'type'})
				{
					$refUVI->{'type'}  = 2;
				}
				#------当前牌组合是品级点数
				if(2 == $refUVI->{'type'})
				{		
					if(($cards[$refPlayerCards->[$unicInput{$tmpKey}]][0] / 3) !=  ($refUVI->{'cardName'} / 3))
					{
						$refUVI->{'isValid'} = 0;
						last;
					}
					$refUVI->{'cardName'} = $cards[$refPlayerCards->[$unicInput{$tmpKey}]][0];  
				}
			}
			#------这张牌是点数的处理逻辑
			else
			{	
				#------当前牌组合是品级
				if(0 == $refUVI->{'type'})
				{
					$refUVI->{'type'}  = 2;
				}
				#------当前牌组合是点数
				if(1 ==  $refUVI->{'type'})
				{
					if($refUVI->{'cardName'} ne $cards[$refPlayerCards->[$unicInput{$tmpKey}]][0])
					{
						 $refUVI->{'isValid'} = 0;
						 last;
					}
				}
				#------当前牌组合是品级点数
				if(2 == $refUVI->{'type'})
				{		
					if( int($cards[$refPlayerCards->[$unicInput{$tmpKey}]][0] / 3) !=  int($refUVI->{'cardName'} / 3))
					{
						#$checkError =$cards[$refPlayerCards->[$unicInput{$tmpKey}]][0] / 3;
						#print "\ncheckError $checkError";
						#$checkError = $refUVI->{'cardName'} / 3;
						#print "\ncheckError $checkError";

					   	$refUVI->{'isValid'} = 0;
					   	last;
					}			
				}
			}
		}
	}

	#使用了很多的方法都不能从 数组的引用 得到数组信息（数组长度），看来数组的引用就是纯粹的一个内存位置，
	#perl不能从这个为内存位置找到数组应该信息，可以从这个位置访问数组内容
	
	#@tmpArr_ = @$refUVI->{'cardsArr'};
	#print "\ntmpArr -- $tmpArr_[0]";

	#print "\n";
	#$i = 0;
	#foreach(@$tmpArrValue)
	#foreach (@$refUVI->{'cardsArr'})
	#for($i=0; $i<3; ++$i)
	#{
	#	print "$i - $$refUVI->{'cardsArr'}[$i++]\t";
	#}
}
#}}}

#------ 将随机发到用户手中的牌，按大小点数排序
#{{{
sub sortCards
{
	my($tmpPlayer) = @_;
	my($refPlayerCards);
	my($tmpvLoop);
	my($tmpPIndex);
	my($tmpPlayerName);

	if($tmpPlayer eq 'a' || $tmpPlayer eq 'A' )
	{
		$tmpPlayerName = 'player A';
		$tmpPIndex = 2;
		$refPlayerCards = $playersCards[0];
	}
	elsif($tmpPlayer eq 'b' || $tmpPlayer eq 'B')
	{
		$tmpPlayerName = 'player B';
		$tmpPIndex = 4;
		$refPlayerCards = $playersCards[1];
	}
	elsif($tmpPlayer eq 'c' || $tmpPlayer eq 'C')
	{
		$tmpPlayerName = 'player C';
		$tmpPIndex = 6;
		$refPlayerCards = $playersCards[2];
	}
	elsif($tmpPlayer eq 'd' || $tmpPlayer eq 'D')
	{
		$tmpPlayerName = 'player D';
		$tmpPIndex = 8;
		$refPlayerCards = $playersCards[3];
	}
	else
	{
		print "wrong input for sortCards call\n\n";
		return "";
	}

	print "sort cards of $tmpPlayerName ......\n\n";

	my($tmpSwap);
	for($i = 1; $i<28; ++$i)
	{
		for($j = 0; $j<28-$i; ++$j)
		{
			if($cards[$refPlayerCards->[$j]][0]>$cards[$refPlayerCards->[$j+1]][0])
			{
				$tmpSwap = $refPlayerCards->[$j];
				$refPlayerCards->[$j] = $refPlayerCards->[$j+1];
				$refPlayerCards->[$j+1] = $tmpSwap;
			}
		}
	}
	
 	for($i = 20; $i<28; ++$i)
	{
		if($cards[$refPlayerCards->[$i]][1] == 0)
		{
			$cards[$refPlayerCards->[$i]][3] = $tmpPIndex;
		}
	}
}
#}}}

#------ 用户当前牌面显示 手中的，赢下的，丢失的
#{{{
sub showPlayerCards
{
	my($tmpPlayer) = @_;

	my($refPlayerCards);
	my($tmpvLoop);

	print("\n\n");

	if(exists($playerToIndex{$tmpPlayer}))
	{
		$refPlayerCards = $playersCards[$playerToIndex{$tmpPlayer}];
	}
	else
	{
		print "wrong input for sowPlayCards call\n\n";
		return;
	}

	print "player $tmpPlayer cards in your hand: \n";

	my($pressKey);
	$pressKey = 'a';
	
	for($i=0; $i<28; ++$i)
	{
		$tmpCardState = $cards[$refPlayerCards->[$i]][3];
		if($tmpCardState == 9) #---card lose
		{
			print "\n$pressKey => $cardName{$cards[$refPlayerCards->[$i]][0]}\t\t L\t$cards[$refPlayerCards->[$i]][4]";
		}
		elsif($tmpCardState%2 == 0) #---card get
		{
			print "\n$pressKey => $cardName{$cards[$refPlayerCards->[$i]][0]}\t\t G\t$cards[$refPlayerCards->[$i]][4]";
		}
		else #---card in hand
		{
			print "\n$pressKey => $cardName{$cards[$refPlayerCards->[$i]][0]}\t\t -";
		}

		$pressKey = chr(ord($pressKey)+1);

	}
	return;

	#my(@tmpArr);
	#@tmpArr = @$refPlayerCards; 
	#print @tmpArr;
	#
	#for($i=0; $i<28; ++$i)
	#{
	#	$tmpCardState = $cards[$tmpArr[$i]][3];
	#	if($tmpCardState == 9) #---card lose
	#	{
	#		print "\n$pressKey => $cardName{$cards[$tmpArr[$i]][0]}\t\t L";
	#	}
	#	elsif($tmpCardState%2 == 0) #---card get
	#	{
	#		print "\n$pressKey => $cardName{$cards[$tmpArr[$i]][0]}\t\t G";
	#	}
	#	else #---card in hand
	#	{
	#		print "\n$pressKey => $cardName{$cards[$tmpArr[$i]][0]}\t\t-";
	#	}
	#
	#	$pressKey = chr(ord($pressKey)+1);
	#}
}
#}}}

#------to test whether a key/value pair can be delete where loop to visit it
#{{{
sub testHashDelete
{
	%days = ("Sunday"    =>0,
		"Monday"    =>1,
		"Tueseday"  =>2,
		"Wednseday" =>3,
		"Turseday"  =>4,
		"Friday"    =>5,
		"Santurday" =>6);

	foreach $testTmpKey (keys %days)
	{
		print "$testTmpKey $days{$testTmpKey}\n";
		if($testTmpKey eq 'Friday')
		{
			delete $days{'Friday'};
		}
		#print "$testTmpKey $days{$testTmpKey}\n";

	}

	foreach $testTmpKey (keys %days)
	{
		print "$testTmpKey $days{$testTmpKey}\n";
		if($testTmpKey eq 'Friday')
		{
			delete $days{'Friday'};
		}
		#print "$testTmpKey $days{$testTmpKey}\n";

	}
}
#}}}
